package me.baicai.weixin.identity.service.impl;

import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.TemplateUtil;
import me.baicai.domain.vo.EmailVo;
import me.baicai.modules.belldandy.gcb.domain.FinancePayroll;
import me.baicai.modules.belldandy.gcb.domain.Project;
import me.baicai.modules.belldandy.gcb.repository.ProjectRepository;
import me.baicai.modules.belldandy.gcb.repository.UserDividendRepository;
import me.baicai.modules.belldandy.gcb.repository.UserProjectRepository;
import me.baicai.modules.system.domain.User;
import me.baicai.modules.system.repository.UserRepository;
import me.baicai.service.EmailService;
import me.baicai.utils.StringUtils;
import me.baicai.weixin.application.BasicService;
import me.baicai.weixin.application.Result;
import me.baicai.weixin.entity.gcb.Finance;
import me.baicai.weixin.entity.gcb.PageEntity;
import me.baicai.weixin.entity.gcb.Query;
import me.baicai.weixin.identity.repository.*;
import me.baicai.weixin.identity.service.PCService;
import me.baicai.weixin.provider.repository.FaultRecordRepository;
import me.baicai.weixin.provider.utils.ExcelUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;


@Service
public class PCServiceImpl extends BasicService implements PCService
{

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private DeviceRepository deviceRepository;

    @Autowired
    private AgentApplyRepository agentApplyRepository;

    @Autowired
    private LoginRepository loginRepository;

    @Autowired
    private FaultRecordRepository faultRecordRepository;

    @Autowired
    private FinanceRepository financeRepository;

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private FinancePayrollRepository financePayrollRepository;

    @Autowired
    private EmailService emailService;

    @Autowired
    private UserProjectRepository projectRepository;

    @Autowired
    private UserDividendRepository dividendRepository;

    @Autowired
    private ProjectRepository repository;

    @Override
    public Result order(Query query)
    {
        Pageable pageable = new PageEntity(query.getPage(), query.getSize(), Sort.Direction.DESC,
            "created");
        Map map = new HashMap();
        if (StringUtils.isNotBlank(query.getType()) && StringUtils.isNotBlank(query.getValue()))
        {
            switch (query.getType())
            {
                case "id":
                    return this.success(
                        orderRepository.findAllByIdLike("%" + query.getValue() + "%", pageable));
                case "end":
                    return this.success(orderRepository.findAllByEnd(query.getValue(), pageable));
                case "create":
                    return this.success(
                        orderRepository.findAllByCreate(query.getValue(), pageable));
                case "status":
                    return this.success(
                        orderRepository.findAllByOrderstatus(query.getValue(), pageable));
                case "devicesn":
                    return this.success(
                        orderRepository.findAllByDevicesnLike("%" + query.getValue() + "%",
                            pageable));
                case "customerid":
                    return this.success(
                        orderRepository.findAllByCustomerid(query.getValue(), pageable));
                case "shopid":
                    return this.success(
                        orderRepository.findAllByShopid(Integer.valueOf(query.getValue()),
                            pageable));
                case "agentId":
                    return this.success(
                        orderRepository.findAllByAgentid(Integer.valueOf(query.getValue()),
                            pageable));
            }
            return this.success(map);
        }
        return this.success(orderRepository.findAll(pageable));
    }

    @Override
    public Result order(String id)
    {
        Map map = new HashMap();
        map.put("agent", orderRepository.findAgnetByOrderId(id));
        map.put("shop", orderRepository.findShopByOrderId(id));
        map.put("eng", orderRepository.findEngByOrderId(id));
        map.put("customer", orderRepository.findCustomerByOrderId(id));
        return this.success(map);
    }

    @Override
    public Result device(Query query)
    {
        Pageable pageable = new PageEntity(query.getPage(), query.getSize(), Sort.Direction.DESC,
            "id");
        Map map = new HashMap();
        if (StringUtils.isNotBlank(query.getType()) && StringUtils.isNotBlank(query.getValue()))
        {
            switch (query.getType())
            {
                case "sn":
                    map.put("numberOfElements",
                        deviceRepository.findByPCSnCount("%" + query.getValue() + "%"));
                    map.put("entity",
                        deviceRepository.findByPCSn("%" + query.getValue() + "%", pageable));
                    return this.success(map);
                case "shopName":
                    map.put("numberOfElements",
                        deviceRepository.findByPCShopNameCount("%" + query.getValue() + "%"));
                    map.put("entity",
                        deviceRepository.findByPCShopName("%" + query.getValue() + "%", pageable));
                    return this.success(map);
                case "shopId":
                    map.put("numberOfElements",
                        deviceRepository.findByPCShopIdCount("%" + query.getValue() + "%"));
                    map.put("entity",
                        deviceRepository.findByPCShopId("%" + query.getValue() + "%", pageable));
                    return this.success(map);
                case "agent":
                    map.put("numberOfElements",
                        deviceRepository.findByPCAgentCount("%" + query.getValue() + "%"));
                    map.put("entity",
                        deviceRepository.findByPCAgent("%" + query.getValue() + "%", pageable));
                    return this.success(map);
                case "agentId":
                    map.put("numberOfElements",
                        deviceRepository.findByPCAgentIdCount("%" + query.getValue() + "%"));
                    map.put("entity",
                        deviceRepository.findByPCAgentId("%" + query.getValue() + "%", pageable));
                    return this.success(map);
            }
        }

        map.put("numberOfElements", deviceRepository.count());
        map.put("entity", deviceRepository.findByPCDe(pageable));
        return this.success(map);
    }

    @Override
    public Result apply(Query query)
    {
        Pageable pageable = new PageEntity(query.getPage(), query.getSize(), Sort.Direction.DESC,
            "id");
        if (StringUtils.isEmpty(query.getType()))
        {
            return this.success(agentApplyRepository.findAll(pageable));
        }
        else
        {
            return this.success(agentApplyRepository.findAllByType(query.getType(), pageable));
        }
    }

    /**
     * 统计用户数量 / 周订单数量 / 周订单金额 / 周退款数量
     * 当日新增用户数量 /  当日新增订单数量 / 当日订单金额 / 当日退款数量
     *
     * @return
     */
    @Override
    public Result information()
    {
        Map<String, Object> map = new HashMap<>();
        map.put("allUserCount", loginRepository.count());
        map.put("weeklyOrderCount", orderRepository.findAllByWeeklyOrderCount(2));
        map.put("weeklyOrderAmount", orderRepository.findAllByWeeklyOrderAmount(2));
        map.put("weeklyOrderRefundCount", orderRepository.findAllByWeeklyOrderCount(0));
        map.put("weeklyOrderRefundAmount", orderRepository.findAllByWeeklyOrderAmount(0));

        // 获取今天结束的数据
        map.put("newUserCount", loginRepository.getTodayCount());
        map.put("newOrderCount", orderRepository.findAllByNowOrderCount(2));
        map.put("newOrderAmount", orderRepository.findAllByNowOrderAmount(2));
        map.put("newOrderRefundCount", orderRepository.findAllByNowOrderCount(0));
        map.put("newOrderRefundAmount", orderRepository.findAllByNowOrderAmount(0));

        Map<String, Object> sevenChart = new HashMap<>();
        sevenChart.put("OrderCount", orderRepository.sevenOrderCount(2, 7));
        sevenChart.put("OrderAmount", orderRepository.sevenOrderAmount(2, 7));
        sevenChart.put("OrderRefundCount", orderRepository.sevenOrderCount(0, 7));
        sevenChart.put("OrderRefundAmount", orderRepository.sevenOrderAmount(0, 7));
        map.put("sevenChart", sevenChart);

        Map<String, Object> thirtyChart = new HashMap<>();
        thirtyChart.put("OrderCount", orderRepository.sevenOrderCount(2, 30));
        thirtyChart.put("OrderAmount", orderRepository.sevenOrderAmount(2, 30));
        thirtyChart.put("OrderRefundCount", orderRepository.sevenOrderCount(0, 30));
        thirtyChart.put("OrderRefundAmount", orderRepository.sevenOrderAmount(0, 30));
        map.put("thirtyChart", thirtyChart);

        return this.success(map);
    }

    @Override
    public Result faultRecord(Query query)
    {
        Pageable pageable = new PageEntity(query.getPage(), query.getSize(), Sort.Direction.DESC,
            "id");
        return this.success(faultRecordRepository.findAll(pageable));
    }

    @Override
    public Result financeData(String yearIn, String yearOut, String monthIn, String monthOut)
    {

        Map map = new HashMap();
        map.put("monthIn", financeRepository.findAllByCreateDate(monthIn, "in"));
        map.put("monthOut", financeRepository.findAllByCreateDate(monthOut, "out"));

        // 分别获取in/out曲线
        List<String> in = financeRepository.findTypeByYear(yearIn, "in");
        Map yin = new HashMap();
        in.forEach(arr -> {
            yin.put(arr, financeRepository.findAllByYearAndType(yearIn, "in", arr));
        });
        map.put("yearIn", yin);

        List<String> out = financeRepository.findTypeByYear(yearIn, "out");
        Map yout = new HashMap();
        out.forEach(arr -> {
            yout.put(arr, financeRepository.findAllByYearAndType(yearOut, "out", arr));
        });
        map.put("yearOut", yout);

        map.put("pool", financeRepository.findPool());

        return this.success(map);
    }

    @Override
    public Result finance(Finance finance)
    {
        financeRepository.saveAndFlush(finance);
        return this.success();
    }

    @Override
    public Result finance(Query query)
    {

        Pageable pageable = new PageEntity(query.getPage(), query.getSize(), Sort.Direction.DESC,
            "id");
        if (StringUtils.isEmpty(query.getType()))
        {
            return this.success(financeRepository.findAll(pageable));
        }

        switch (query.getType())
        {
            case "created":
                return this.success(
                    financeRepository.findAllByCreatedLike(query.getValue(), pageable));
            case "type":
                return this.success(financeRepository.findAllByType(query.getValue(), pageable));
            case "createDate":
                return this.success(financeRepository.findAll(pageable));
        }
        return null;
    }

    @Override
    public Result financeUpload(MultipartFile file)
    {
        List<FinancePayroll> list = ExcelUtils.readFinance(file);
        list.forEach(arr -> {
            User user = userRepository.findByEmployeename(arr.getName());
            financePayrollRepository.deleteAllByTargetdAndName(arr.getTargetd(), arr.getName());
            if (null == user)
            {
                arr.setEmail("未匹配-请手动输入");
                return;
            }
            arr.setEmail(user.getEmail());
            arr.setUid(user.getId());
        });
        financePayrollRepository.saveAll(list);
        list.forEach(arr -> {
            Finance finance = new Finance();
            finance.setType("out");
            finance.setAmount(arr.getField17());
            finance.setSouce("工资发放");
            finance.setRemark(arr.getField1() + arr.getTargetd());
            finance.setCreateDate(arr.getCreated());
            finance.setCreated("System");
            financeRepository.save(finance);
        });
        return this.success();
    }

    @Override
    public Result financePayroll(String targe)
    {
        return this.success(financePayrollRepository.findAllByTargetd(targe));
    }

    @Override
    public Result financePayroll(FinancePayroll financePayroll)
    {
        financePayroll.setUpdated(new Date());
        financePayrollRepository.saveAndFlush(financePayroll);

        financeRepository.deleteAllByCreated(
            financePayroll.getField1() + financePayroll.getTargetd());
        Finance finance = new Finance();
        finance.setType("out");
        finance.setAmount(financePayroll.getField17());
        finance.setSouce("工资发放");
        finance.setRemark(financePayroll.getField1() + financePayroll.getTargetd());
        finance.setCreateDate(financePayroll.getCreated());
        finance.setCreated(financePayroll.getField1() + financePayroll.getTargetd());
        financeRepository.save(finance);
        return this.success();
    }

    @Override
    public Result financePayroll(Integer id)
    {
        FinancePayroll financePayroll = financePayrollRepository.findFinancePayrollById(id);
        financePayrollRepository.deleteById(id);
        financeRepository.deleteAllByCreated(
            financePayroll.getField1() + financePayroll.getTargetd());
        return this.success();
    }

    @Override
    public Result sendFinancePayroll(String id)
        throws Exception
    {
        if (id.length() == 7)
        {
            List<FinancePayroll> list = financePayrollRepository.getAllByTargetd(id);
            list.forEach(arr -> {
                Map map = new HashMap();
                map.put("payroll", arr);
                EmailVo emailVo;
                String content;
                TemplateEngine engine = TemplateUtil.createEngine(
                    new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));
                Template template = engine.getTemplate("email/payroll.ftl");
                content = template.render(map);
                String title = arr.getName() + "同事，您的 " + arr.getTargetd() + "月工资单已经发放";
                emailVo = new EmailVo(Arrays.asList(arr.getEmail()), title, content);
                try
                {
                    emailService.send(emailVo, emailService.find());
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            });
            return this.success();
        }
        Map map = new HashMap();
        FinancePayroll financePayroll = financePayrollRepository.findFinancePayrollById(
            Integer.valueOf(id));
        map.put("payroll", financePayroll);
        EmailVo emailVo;
        String content;
        TemplateEngine engine = TemplateUtil.createEngine(
            new TemplateConfig("template", TemplateConfig.ResourceMode.CLASSPATH));
        Template template = engine.getTemplate("email/payroll.ftl");
        content = template.render(map);
        String title =
            financePayroll.getName() + "同事，您的 " + financePayroll.getTargetd() + "月工资单已经发放";
        emailVo = new EmailVo(Arrays.asList(financePayroll.getEmail()), title, content);
        emailService.send(emailVo, emailService.find());
        return this.success();
    }

    @Override
    public Result myFinance(Integer uid)
    {
        String name = financePayrollRepository.findUserName(uid);

        Map map = new HashMap();
        // 工资条
        map.put("payroll", financePayrollRepository.findAllByName(name));

        // 关联的项目
        map.put("userProject", projectRepository.getUserProject(uid));

        // 关联分红
        map.put("userDividend", dividendRepository.getUserDividend(uid));

        map.put("资金池", dividendRepository.资金池());

        return this.success(map);
    }

    @Override
    public Result projectInfo(Integer uid, Integer pid, String date, String type)
    {
        if (type.equalsIgnoreCase("commission"))
        {
            return this.success(projectRepository.projectInfo(uid, pid, date));
        }
        else
        {
            Project project = repository.findProjectById(pid);

            Map map = new HashMap();

            if (dividendRepository.获取字典("结算方式").equalsIgnoreCase("月结"))
            {
                Float out = dividendRepository.月度求和("out", date);

                if (project.getName().equalsIgnoreCase("共成宝"))
                {
                    Float in = dividendRepository.项目月度求和("共享", date, "in");
                    String rate = dividendRepository.获取字典("充电器负担比例");
                    map.put("in", in);
                    map.put("out", out);
                    map.put("rate", rate);
                    map.put("dividend", dividendRepository.getUserDividend(uid,pid).getCommission());
                }
                else if (project.getName().equalsIgnoreCase("传统事业"))
                {
                    Float in = dividendRepository.项目月度求和("其他", date, "in");
                    String rate = dividendRepository.获取字典("工厂负担比例");
                    map.put("in", in);
                    map.put("out", out);
                    map.put("rate", rate);
                    map.put("dividend", dividendRepository.getUserDividend(uid,pid).getCommission());
                }
                else
                {
                    Float in = dividendRepository.项目月度求和("外贸", date, "in");
                    String rate = dividendRepository.获取字典("外贸负担比例");
                    map.put("in", in);
                    map.put("out", out);
                    map.put("rate", rate);
                    map.put("dividend", dividendRepository.getUserDividend(uid,pid).getCommission());
                }
            }

            return this.success(map);
        }
    }
}
